package com.pro.core.aspect;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Sets;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.ui.ExtendedModelMap;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.support.AbstractMultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.*;

@Aspect
@Component
public class RequestLogAspect {
    private final Log logger = LogFactory.getLog(RequestLogAspect.class);

    @Pointcut("" +
            "execution( * com.pro.admin.web.guanwang..*.*(..)) || "
    + "execution( * com.pro.app.controller..*.*(..))")
    public void pointcut(){}

    private static Set<String> paths = Sets.newHashSet();
    static {
        paths.add("/api/invoice/add");

    }

    @Around("pointcut()")
    public Object handle(JoinPoint joinPoint) throws Throwable{
        preHandle(joinPoint);
        Object retVal = ((ProceedingJoinPoint) joinPoint).proceed();
        postHandle(retVal,joinPoint);
        return retVal;
    }

    private void preHandle(final JoinPoint joinPoint) {
        HttpServletRequest request = ( (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes() ).getRequest();
        logger.info("*************************************************************************");
        logger.info("【"+request.getRequestURI()+"】" + "请求参数:{"+ getRequestString(joinPoint)+"}," +
                        " headers: {"+getHeaderString(request)+"}" );
    }

    private void postHandle(Object retVal,JoinPoint joinPoint) {
        HttpServletRequest request = ( (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes() ).getRequest();
/*        logger.info("【"+request.getRequestURI()+"】" + "返回结果 request: {}, response: {}", getRequestString(request,joinPoint),
                JsonUtils.bean2Json(retVal));*/
        logger.info("【"+request.getRequestURI()+"】" + "返回结果:{" + JSON.toJSONString(retVal) + "}");
        logger.info("*************************************************************************");
        logger.info(" ");
        String url = request.getRequestURI();
        String contextPath = request.getContextPath();
        if(!paths.contains(url.replace(contextPath,""))){
            return;
        }
    }

    private String getRequestString(HttpServletRequest request,JoinPoint joinPoint){
        String content_type = request.getHeader("content-type");
        if(null != content_type && content_type.contains("application/json")){
            return getRequestString(joinPoint);
        }else {
            return getRequestString(request);
        }
    }

    private String getRequestString(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        StringBuffer buffer = new StringBuffer("{");
        try {
            if (null != args) {
                for (int i=0, size = args.length; i < size; i++) {
                    if (null == args[i] || args[i] instanceof ExtendedModelMap || args[i] instanceof HttpServletRequestWrapper
                            || args[i] instanceof AbstractMultipartHttpServletRequest
                            || args[i].getClass().getName().startsWith("org.apache.catalina.connector.ResponseFacade")
                            || args[i].getClass().getName().startsWith("[Lorg.springframework.web.multipart.MultipartFile")) continue;
                    buffer.append(JSON.toJSONString(args[i]));
                    if (i != size - 1) buffer.append(",");
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        buffer.append("}");
        return buffer.toString();
    }

    private  String getRequestString(HttpServletRequest request) {
        Map<String, String[]> map = request.getParameterMap();
        Set<Map.Entry<String, String[]>> set = map.entrySet();
        StringBuffer sb = new StringBuffer();
        sb.append("{");
        Iterator<Map.Entry<String, String[]>> it = set.iterator();
        while (it.hasNext()) {
            Map.Entry<String, String[]> entry = it.next();
            sb.append(entry.getKey() + ":");
            for (String i : entry.getValue()) {
                sb.append(i);
            }
            if(it.hasNext()){
                sb.append(",");
            }
        }
        sb.append("}");
        return sb.toString();
    }

    private String getHeaderString(HttpServletRequest request){
        StringBuffer sb = new StringBuffer();
        sb.append("{");
        Enumeration<String> headers = request.getHeaderNames();
        int i = 0;
        while (headers.hasMoreElements()) {
            String header = headers.nextElement();
            if (i > 0)
                sb.append(", ");
            sb.append(header + ": " + request.getHeader(header));
            i++;
        }
        sb.append("}");
        return sb.toString();
    }
}
